Skip to content

Fix streaming tools support for string annotations and serialization#4447

Open
ItsMacto wants to merge 7 commits intogoogle:mainfrom
ItsMacto:fix-streaming-tools-support
Open

Fix streaming tools support for string annotations and serialization#4447
ItsMacto wants to merge 7 commits intogoogle:mainfrom
ItsMacto:fix-streaming-tools-support

Conversation

@ItsMacto
Copy link

@ItsMacto ItsMacto commented Feb 11, 2026

Fixed streaming tools (returning AsyncGenerator) failing schema generation with from __future__ import annotations and causing serialization errors during execution.
This change ensures string type hints are correctly resolved to identify streaming tools and consumes the async_generator result into a list before returning, making it serializable.
Added regression tests for both schema generation and tool execution.

Link to Issue or Description of Change

1. Link to an existing issue (if applicable):

2. Or, if no issue exists, describe the change:

Problem:

  1. Schema Generation: When from __future__ import annotations is used, type hints are stored as strings. The FunctionTool schema generator failed to resolve these string annotations for AsyncGenerator return types, causing it to fail to identify the tool as streaming.
  2. Serialization: FunctionTool.run_async returned the raw async_generator object. The ADK runner attempted to serialize this object for event logging, raising a TypeError because async_generator objects cannot be pickled.

Solution:

  1. Schema Generation: Modified build_function_declaration in src/google/adk/tools/_automatic_function_calling_util.py to reuse the existing annotation_under_future dictionary (which contains resolved type hints). This correctly identifies AsyncGenerator types even when annotations are strings.
  2. Serialization: Updated FunctionTool.run_async in src/google/adk/tools/function_tool.py to detect if the function result is an AsyncGenerator. If so, it consumes the generator into a list and returns the list of yielded items, ensuring the result is serializable.

Testing Plan

Unit Tests:

  • I have added or updated unit tests for my change.

  • All unit tests pass locally.

  • tests/unittests/tools/test_build_function_declaration.py : Verified schema generation for string-annotated AsyncGenerator.

  • tests/unittests/tools/test_function_tool.py : Verified run_async consumes generator and returns list.

Manual End-to-End (E2E) Tests:

Verified locally with a reproduction script that successfully generated the schema and executed the tool without serialization errors.

Checklist

  • I have read the CONTRIBUTING.md document.
  • I have performed a self-review of my own code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • I have manually tested my changes end-to-end.
  • Any dependent changes have been merged and published in downstream modules.

@gemini-code-assist
Copy link
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@adk-bot adk-bot added the tools [Component] This issue is related to tools label Feb 11, 2026
@ItsMacto
Copy link
Author

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request effectively addresses two issues with streaming tools: one related to schema generation with string annotations and another concerning the serialization of async_generator results. The changes correctly resolve deferred type hints and consume async generators into lists, and the new regression tests validate these fixes. I have provided a couple of suggestions to enhance code style and test robustness.

ItsMacto and others added 2 commits February 11, 2026 08:37
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
@ItsMacto
Copy link
Author

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request effectively addresses issues with streaming tools that use string annotations and ensures their results are serializable. The changes correctly resolve deferred type hints for AsyncGenerator and consume the async generator into a list, preventing serialization errors. The new regression tests are well-written and validate these fixes. I have one suggestion to also handle synchronous generators for consistency with the schema generation logic and to prevent similar serialization issues.

@ItsMacto ItsMacto force-pushed the fix-streaming-tools-support branch from be96b7b to 96f3c86 Compare February 11, 2026 14:04
 to use a result-based duck typing approach. Traced all callers (FunctionTool.run_async, CrewaiTool.run_async, McpTool override)
@ItsMacto
Copy link
Author

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request correctly addresses two issues related to streaming tools: schema generation with string annotations and serialization of generator results. The approach to resolve string type hints in _automatic_function_calling_util.py is sound, and the addition of regression tests for both fixes is excellent.

However, I've identified a potential issue in the refactored _invoke_callable method in function_tool.py. The current order of checks can lead to an unconsumed generator being returned if an async function returns a synchronous generator, which would cause a serialization error. I've provided a suggestion to make the logic more robust by handling awaitables first and then checking the result for generators.

@ryanaiagent ryanaiagent self-assigned this Feb 11, 2026
@ryanaiagent ryanaiagent added the request clarification [Status] The maintainer need clarification or more information from the author label Feb 11, 2026
@ryanaiagent
Copy link
Collaborator

Hi @ItsMacto , Thank you for your contribution! We appreciate you taking the time to submit this pull request.
Can you please address the suggestions.

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
@ItsMacto
Copy link
Author

/gemini review

@gemini-code-assist
Copy link
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@ItsMacto
Copy link
Author

@ryanaiagent Yes, I agree with the comment. Did not think of that. Should be good now!

@ItsMacto ItsMacto requested a review from ryanaiagent February 12, 2026 04:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

request clarification [Status] The maintainer need clarification or more information from the author tools [Component] This issue is related to tools

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Streaming tools example in the documentation does not work

3 participants